home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / doc.lha / doc.doc / scanex.doc < prev    next >
Text File  |  1992-09-25  |  43KB  |  1,888 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11. ___________________________________________________________________
  12.  
  13.  
  14.                                    Selected Examples of
  15.                                    Scanner Specifications
  16.  
  17.                                    J. Grosch
  18.  
  19.  
  20. ___________________________________________________________________
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. ___________________________________________________________________
  51.                                    GESELLSCHAFT FUeR MATHEMATIK
  52.                                    UND DATENVERARBEITUNG MBH
  53.  
  54.                                    FORSCHUNGSSTELLE FUeR
  55.                                    PROGRAMMSTRUKTUREN
  56.                                    AN DER UNIVERSITAeT KARLSRUHE
  57. ___________________________________________________________________
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.                                    Project
  76.  
  77.                              Compiler Generation
  78.  
  79.          ___________________________________________________________
  80.  
  81.                  Selected Examples of Scanner Specifications
  82.  
  83.  
  84.                                  Josef Grosch
  85.  
  86.  
  87.                                  Mar. 8, 1988
  88.  
  89.          ___________________________________________________________
  90.  
  91.  
  92.                                  Report No. 7
  93.  
  94.  
  95.                              Copyright c 1988 GMD
  96.  
  97.  
  98.             Gesellschaft fuer Mathematik und Datenverarbeitung mbH
  99.                 Forschungsstelle an der Universitaet Karlsruhe
  100.                           Vincenz-Priesznitz-Str. 1
  101.                                D-7500 Karlsruhe
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.                             Scanner Specification                            2
  135.  
  136.  
  137. 1.  Introduction
  138.  
  139.      Among the tokens to be recognized by scanners are a few that require  non
  140. trivial processing: comments, strings, and character constants.  Even identif-
  141. iers and keywords may cause some trouble if the  language  defines  upper-case
  142. and  lower-case  letters  to  have  the same meaning.  The problems with these
  143. tokens are the following:
  144.  
  145. -    maintaining the line count during tokens extending on several lines
  146.  
  147. -    maintaining the column count during tokens containing tab characters
  148.  
  149. -    computation of the source position of tokens extending on  several  lines
  150.      or of compound tokens which are recognized as a sequence of subtokens
  151.  
  152. -    nested comments
  153.  
  154. -    report unclosed strings and comments as errors
  155.  
  156. -    computing the internal representation of strings
  157.  
  158. -    conversion of escape sequences  such  as  doubled  string  delimiters  or
  159.      preceding escape characters
  160.  
  161. -    normalization of upper-case and lower-case letters
  162.  
  163. The following chapters  contain  solutions  to  the  above  problems  for  the
  164. languages Pascal, Modula, C, and Ada. The solutions are scanner specifications
  165. suitable as input for the scanner generator Rex [Gro87].  The  primary  inten-
  166. tion  of  this paper is to serve as a reference manual containing examples for
  167. non trivial cases.  All specifications use C as  target  language  except  the
  168. chapter on Modula which uses Modula.  The Appendix contains a complete scanner
  169. specification for Ada with Modula as target language.
  170.  
  171. 2.  Pascal
  172.  
  173. 2.1.  Comments
  174.  
  175. Problems to solve:
  176.  
  177. -    unclosed comments
  178.  
  179. -    newline characters
  180.  
  181. -    tab characters
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.                             Scanner Specification                            3
  200.  
  201.  
  202. Solution:
  203. EOF     {IF yyStartState = Comment THEN Error ("unclosed comment"); END;}
  204.  
  205. DEFINE  CmtCh   = - {*\}\t\n}.
  206.  
  207. START   Comment
  208.  
  209. RULE
  210.  
  211.            "(*" | "{"     :- {yyStart (Comment);}
  212. #Comment#  "*)" | "}"     :- {yyStart (STD);}
  213. #Comment#  "*"  | CmtCh + :- {}
  214.  
  215.  
  216.      Comments are processed in a separate start state called Comment.   Every-
  217. thing  is  skipped  in this state except closing comment brackets which switch
  218. back to start state STD.  The single characters '*' or '}' which can  start  a
  219. closing  comment bracket have to be skipped separately. Otherwise closing com-
  220. ment brackets would not be recognized because of the "longest match"  rule  of
  221. Rex.   An unclosed comment is indicated by reaching end of file while in start
  222. state Comment.  We presuppose the existence of a  procedure  Error  to  report
  223. this  condition.  We don't need to care about tab and newline characters other
  224. than excluding them from the set CmtCh because the two rules needed  for  this
  225. problem are already predefined by Rex:
  226.  
  227. #Comment#  \t :- {yyTab;}
  228. #Comment#  \n :- {yyEol (0);}
  229.  
  230.  
  231. 2.2.  Identifiers
  232.  
  233. Problems to solve:
  234.  
  235. -    normalization of upper-case and lower-case letters
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243.  
  244.  
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.                             Scanner Specification                            4
  265.  
  266.  
  267. Solution:
  268. EXPORT  {
  269. # include "Idents.h"
  270. # include "Positions.h"
  271. typedef struct {
  272.    tPosition Position;
  273.    tIdent    Ident;
  274. } tScanAttribute;
  275. extern void ErrorAttribute ();
  276. }
  277.  
  278. GLOBAL  {
  279. # define TokIdentifier ...
  280. void ErrorAttribute (Token, Attribute)
  281.    int Token;
  282.    tScanAttribute * Attribute;
  283.    {
  284.       Attribute->Ident = NoIdent;
  285.    }
  286. }
  287.  
  288. LOCAL   {char String [256]; int L;}
  289.  
  290. DEFINE  letter  = {A-Z a-z}.
  291.         digit   = {0-9}.
  292.  
  293. RULE
  294.  
  295. letter (letter | digit) * : {L = GetLower (String);
  296.                 Attribute.Ident = MakeIdent (String, L); return TokIdentifier;}
  297.  
  298.  
  299.      Normalization of upper-case and lower-case letters to lower-case is  done
  300. by the predefined operation GetLower of Rex.
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.                             Scanner Specification                            5
  330.  
  331.  
  332. 2.3.  Character Constants
  333.  
  334. Problems to solve:
  335.  
  336. -    conversion
  337.  
  338. -    tab characters
  339.  
  340. Solution:
  341. EXPORT  {
  342. # include "Positions.h"
  343. typedef struct {
  344.    tPosition Position;
  345.    char      Char;
  346. } tScanAttribute;
  347. extern void ErrorAttribute ();
  348. }
  349.  
  350. GLOBAL  {
  351. # define TokCharConst ...
  352. void ErrorAttribute (Token, Attribute)
  353.    int Token;
  354.    tScanAttribute * Attribute;
  355.    {
  356.       Attribute->Char = '\0';
  357.    }
  358. }
  359.  
  360. RULE
  361.  
  362. ''''    : {Attribute.Char = '\''; return TokCharConst;}
  363. ' \t '  : {Attribute.Char = '\t'; yyTab2 (1, 1); return TokCharConst;}
  364. ' ANY ' : {Attribute.Char = TokenPtr [1]; return TokCharConst;}
  365.  
  366.  
  367.      In this example the order of the rules is significant  because  the  last
  368. rule would also match the characters of the preceding one.
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.                             Scanner Specification                            6
  395.  
  396.  
  397. 2.4.  Strings
  398.  
  399. Problems to solve:
  400.  
  401. -    conversion
  402.  
  403. -    doubled delimiters
  404.  
  405. -    tab characters
  406.  
  407. -    unclosed strings (at end of lines)
  408.  
  409. -    source position
  410.  
  411. Solution:
  412. EXPORT  {
  413. # include "StringMem.h"
  414. # include "Positions.h"
  415. typedef struct {
  416.    tPosition  Position;
  417.    tStringRef StringRef;
  418. } tScanAttribute;
  419. extern void ErrorAttribute ();
  420. }
  421.  
  422. GLOBAL  {
  423. # define TokString ...
  424. void ErrorAttribute (Token, Attribute) ...
  425. }
  426.  
  427. LOCAL   {char String [256]; int L;}
  428.  
  429. DEFINE  StrCh   = - {'\t\n}.
  430.  
  431. START   string
  432.  
  433. RULE
  434.  
  435. #STD#    '      :  {yyStart (string); L = 0;}
  436. #string# StrCh +:- {L += GetWord (& String [L]);}
  437. #string# ''     :- {String [L ++] = '\'';}
  438. #string# '      :- {yyStart (STD); String [L] = '\0';
  439.                     Attribute.StringRef = PutString (String, L);
  440.                     return TokString;}
  441. #string# \t     :- {String [L ++] = '\t'; yyTab;}
  442. #string# \n     :- {Error ("unclosed string"); yyEol (0);
  443.                     yyStart (STD); String [L] = '\0';
  444.                     Attribute.StringRef = PutString (String, L);
  445.                     return TokString;}
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.                             Scanner Specification                            7
  460.  
  461.  
  462.      We presuppose the existence of a string  memory  module  StringMem.   The
  463. procedure  PutString stores a string in the string memory and returns a refer-
  464. ence to it which can be used as attribute of the token TokString.
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.                             Scanner Specification                            8
  525.  
  526.  
  527. 2.5.  Keywords
  528.  
  529. Problems to solve:
  530.  
  531. -    normalization of upper-case and lower-case letters
  532.  
  533. Solution:
  534. GLOBAL  {
  535. # define TokAND       ...
  536.    ...
  537. # define TokWITH         ...
  538. void ErrorAttribute (Token, Attribute) ...
  539. }
  540.  
  541. DEFINE  A = {Aa}.
  542.           ...
  543.         Z = {Zz}.
  544.  
  545. RULE
  546.  
  547. A N D           : {return TokAND       ;}
  548.   ...
  549. W I T H         : {return TokWITH      ;}
  550.  
  551.  
  552.      The idea of the solution is to define identifiers A to Z to stand for the
  553. corresponding  upper-case  as  well as lower-case letters. Then specifying the
  554. keywords in upper-case and spaced does the job.
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.                             Scanner Specification                            9
  590.  
  591.  
  592. 3.  Modula
  593.  
  594. 3.1.  Comments
  595.  
  596. Problems to solve:
  597.  
  598. -    nested comments
  599.  
  600. -    unclosed comments
  601.  
  602. -    newline characters
  603.  
  604. -    tab characters
  605.  
  606. Solution:
  607. GLOBAL  {VAR NestingLevel: CARDINAL;}
  608.  
  609. BEGIN   {NestingLevel := 0;}
  610.  
  611. EOF     {IF yyStartState = Comment THEN Error ("unclosed comment"); END;}
  612.  
  613. DEFINE  CmtCh   = - {*(\t\n}.
  614.  
  615. START   Comment
  616.  
  617. RULE
  618.  
  619. #STD, Comment# "(*" :- {INC (NestingLevel); yyStart (Comment);}
  620. #Comment#  "*)" :- {DEC (NestingLevel);
  621.                     IF NestingLevel = 0 THEN yyStart (STD); END;}
  622. #Comment#  "(" | "*" | CmtCh + :- {}
  623.  
  624.  
  625.      We need a variable NestingLevel to count the nesting  depth  of  comments
  626. because it is not possible to specify nested comments by a regular expression.
  627. Comments are processed in a separate start state called  Comment.   Everything
  628. is  skipped  in  this  state  except opening or closing comment brackets which
  629. trigger a change of the nesting level. The single characters '(' and '*' which
  630. can  start  opening or closing comment brackets have to be skipped separately.
  631. Otherwise comment brackets within comment would not be recognized  because  of
  632. the "longest match" rule of Rex.  An unclosed comment is indicated by reaching
  633. end of file while in start state Comment.  We presuppose the  existence  of  a
  634. procedure Error to report this condition.  We don't need to care about tab and
  635. newline characters other than excluding them from the set  CmtCh  because  the
  636. two rules needed for this problem are already predefined by Rex:
  637.  
  638. #Comment#  \t :- {yyTab;}
  639. #Comment#  \n :- {yyEol (0);}
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.                             Scanner Specification                           10
  655.  
  656.  
  657. 3.2.  Strings
  658.  
  659. Problems to solve:
  660.  
  661. -    conversion
  662.  
  663. -    tab characters
  664.  
  665. -    unclosed strings (at end of lines)
  666.  
  667. -    source position
  668.  
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.                             Scanner Specification                           11
  720.  
  721.  
  722. Solution:
  723. EXPORT  {
  724.    FROM StringMem IMPORT tStringRef;
  725.    FROM Positions IMPORT tPosition;
  726.    TYPE tScanAttribute = RECORD
  727.       Position  : tPosition;
  728.       StringRef : tStringRef;
  729.    END;
  730.    PROCEDURE ErrorAttribute (Token: INTEGER; VAR Attribute: tScanAttribute);
  731. }
  732.  
  733. GLOBAL  {
  734.    FROM Strings     IMPORT tString, AssignEmpty, Concatenate, Append;
  735.    FROM StringMem   IMPORT PutString;
  736.  
  737.    CONST TokString = ...;
  738.  
  739.    PROCEDURE ErrorAttribute (Token: INTEGER; VAR Attribute: tScanAttribute);
  740.       BEGIN Attribute.StringRef := ...; END ErrorAttribute;
  741. }
  742.  
  743. LOCAL   {VAR String, S: tString;}
  744.  
  745. DEFINE  StrCh1  = - {'\t\n}.
  746.         StrCh2  = - {"\t\n}.
  747.  
  748. START   Str1, Str2
  749.  
  750. RULE
  751.  
  752. #STD#   '       :  {AssignEmpty (String); yyStart (Str1);}
  753. #Str1#  StrCh1+ :- {GetWord (S); Concatenate (String, S);}
  754. #Str1#  '       :- {yyStart (STD);
  755.                     Attribute.StringRef := PutString (String);
  756.                     RETURN TokString;}
  757. #STD#   \"      :  {AssignEmpty (String); yyStart (Str2);}
  758. #Str2#  StrCh2+ :- {GetWord (S); Concatenate (String, S);}
  759. #Str2#  \"      :- {yyStart (STD);
  760.                     Attribute.StringRef := PutString (String);
  761.                     RETURN TokString;}
  762. #Str1, Str2# \t :- {Append (String, 11C); yyTab;}
  763. #Str1, Str2# \n :- {Error ("unclosed string"); yyEol (0); yyStart (STD);
  764.                     Attribute.StringRef := PutString (String);
  765.                     RETURN TokString;}
  766.  
  767.  
  768.      Again two separate start states are used to recognize the  two  forms  of
  769. Modula-2  strings.  We  presuppose  the  existence of a string handling module
  770. Strings and a string memory module StringMem.  The procedure PutString  stores
  771. a  string in the string memory and returns a reference to it which can be used
  772. as attribute of the token TokString.
  773.  
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.                             Scanner Specification                           12
  784.  
  785.  
  786. 4.  C
  787.  
  788. 4.1.  Comments
  789.  
  790. Problems to solve:
  791.  
  792. -    unclosed comments
  793.  
  794. -    newline characters
  795.  
  796. -    tab characters
  797.  
  798. Solution:
  799. EOF     {if (yyStartState == Comment) Error ("unclosed comment");}
  800.  
  801. DEFINE  CmtCh   = - {*\t\n}.
  802.  
  803. START   Comment
  804.  
  805. RULE
  806.  
  807.            "/*" :- {yyStart (Comment);}
  808. #Comment#  "*/" :- {yyStart (STD);}
  809. #Comment#  "*" | CmtCh + :- {}
  810.  
  811.  
  812.      Comments are processed in a separate start state called Comment.   Every-
  813. thing  is  skipped  in this state except closing comment brackets which switch
  814. back to start state STD.  The single character '*' which can start  a  closing
  815. comment bracket has to be skipped separately. Otherwise closing comment brack-
  816. ets would not be recognized because of the "longest match" rule  of  Rex.   An
  817. unclosed  comment  is  indicated  by reaching end of file while in start state
  818. Comment.  We presuppose the existence of a procedure Error to report this con-
  819. dition.   We  don't  need  to care about tab and newline characters other than
  820. excluding them from the set CmtCh because the two rules needed for this  prob-
  821. lem are already predefined by Rex:
  822.  
  823. #Comment#  \t :- {yyTab;}
  824. #Comment#  \n :- {yyEol (0);}
  825.  
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832.  
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.                             Scanner Specification                           13
  849.  
  850.  
  851. 4.2.  Character Constants
  852.  
  853. Problems to solve:
  854.  
  855. -    conversion
  856.  
  857. -    escape sequences
  858.  
  859. -    tab characters
  860.  
  861. Solution:
  862. EXPORT  {
  863. # include "Positions.h"
  864. typedef struct {
  865.    tPosition Position;
  866.    char      Char;
  867. } tScanAttribute;
  868. extern void ErrorAttribute ();
  869. }
  870.  
  871. GLOBAL  {
  872. # define TokChar ...
  873. void ErrorAttribute (Token, Attribute)
  874.    int Token;
  875.    tScanAttribute * Attribute;
  876.    {
  877.       Attribute->Char = '\0';
  878.    }
  879. }
  880.  
  881. LOCAL   {char String [256];}
  882.  
  883. RULE
  884.  
  885. ' \t '        : {Attribute.Char = '\t'; yyTab2 (1, 1); return TokChar;}
  886. ' ANY '       : {Attribute.Char = TokenPtr [1]; return TokChar;}
  887. ' \\ n '      : {Attribute.Char = '\n'; return TokChar;}
  888. ' \\ t '      : {Attribute.Char = '\t'; return TokChar;}
  889. ' \\ v '      : {Attribute.Char = '\v'; return TokChar;}
  890. ' \\ b '      : {Attribute.Char = '\b'; return TokChar;}
  891. ' \\ r '      : {Attribute.Char = '\r'; return TokChar;}
  892. ' \\ f '      : {Attribute.Char = '\f'; return TokChar;}
  893. ' \\ {0-7}[1-3] ' : {(void) GetWord (String);
  894.                  sscanf (String + 2, "%o", & Attribute.Char);
  895.                  return TokChar;}
  896. ' \\ ANY '    : {Attribute.Char = TokenPtr [2]; return TokChar;}
  897.  
  898.  
  899.      In this example the order of the rules is significant because the  second
  900. rule  would also match the characters of the first one. The same holds for the
  901. group of following rules with respect to the last rule.
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.  
  910.  
  911.  
  912.  
  913.                             Scanner Specification                           14
  914.  
  915.  
  916. 4.3.  Strings
  917.  
  918. Problems to solve:
  919.  
  920. -    conversion
  921.  
  922. -    escape sequences
  923.  
  924. -    tab characters
  925.  
  926. -    strings ranging over several lines
  927.  
  928. -    source position
  929.  
  930.  
  931.  
  932.  
  933.  
  934.  
  935.  
  936.  
  937.  
  938.  
  939.  
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.                             Scanner Specification                           15
  979.  
  980.  
  981. Solution:
  982. EXPORT  {
  983. # include "StringMem.h"
  984. # include "Positions.h"
  985. typedef struct {
  986.    tPosition  Position;
  987.    tStringRef StringRef;
  988. } tScanAttribute;
  989. extern void ErrorAttribute ();
  990. }
  991.  
  992. GLOBAL  {
  993. # define TokString ...
  994. void ErrorAttribute (Token, Attribute) ...
  995. }
  996.  
  997. LOCAL   {char String [256], S [5]; int L;}
  998.  
  999. DEFINE  StrCh   = - {"\t\n\\}.
  1000.  
  1001. START   string
  1002.  
  1003. RULE
  1004.  
  1005. #STD#    \"     :  {yyStart (string); L = 0;}
  1006. #string# StrCh+ :- {L += GetWord (& String [L]);}
  1007. #string# \t     :- {String [L ++] = '\t'); yyTab;}
  1008. #string# \\ n   :- {String [L ++] = '\n');}
  1009. #string# \\ t   :- {String [L ++] = '\t');}
  1010. #string# \\ v   :- {String [L ++] = '\v');}
  1011. #string# \\ b   :- {String [L ++] = '\b');}
  1012. #string# \\ r   :- {String [L ++] = '\r');}
  1013. #string# \\ f   :- {String [L ++] = '\f');}
  1014. #string# \\ {0-7}[1-3] :- {(void) GetWord (S);
  1015.                     sscanf (S + 1, "%o", & String [L ++]);}
  1016. #string# \\ ANY :- {(void) GetWord (S); String [L ++] = S [1];}
  1017. #string# \\ \n  :- {yyEol (0); String [L ++] = '\n';}
  1018. #string# \"     :- {yyStart (STD); String [L] = '\0';
  1019.                     Attribute.StringRef = PutString (String, L);
  1020.                     return TokString;}
  1021. #string# \n     :- {Error ("unclosed string"); yyEol (0);
  1022.                     yyStart (STD); String [L] = '\0';
  1023.                     Attribute.StringRef = PutString (String, L);
  1024.                     return TokString;}
  1025.  
  1026.  
  1027.      We presuppose the existence of a string  memory  module  StringMem.   The
  1028. procedure  PutString stores a string in the string memory and returns a refer-
  1029. ence to it which can be used as attribute of the token TokString.
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.                             Scanner Specification                           16
  1044.  
  1045.  
  1046. 5.  Ada
  1047.  
  1048. 5.1.  Identifiers
  1049.  
  1050. Problems to solve:
  1051.  
  1052. -    normalization of upper-case and lower-case letters
  1053.  
  1054. Solution:
  1055. EXPORT  {
  1056. # include "Idents.h"
  1057. # include "Positions.h"
  1058. typedef struct {
  1059.    tPosition Position;
  1060.    tIdent    Ident;
  1061. } tScanAttribute;
  1062. extern void ErrorAttribute ();
  1063. }
  1064.  
  1065. GLOBAL  {
  1066. # define TokIdentifier ...
  1067. void ErrorAttribute (Token, Attribute) ...
  1068. }
  1069.  
  1070. LOCAL   {char String [256]; int L;}
  1071.  
  1072. DEFINE  letter  = {A-Z a-z}.
  1073.         digit   = {0-9}.
  1074.  
  1075. RULE
  1076.  
  1077. letter (_? (letter | digit)+ )* : {L = GetLower (String);
  1078.                 Attribute.Ident = MakeIdent (String, L); return TokIdentifier;}
  1079.  
  1080.  
  1081.      Normalization of upper-case and lower-case letters to lower-case is  done
  1082. by the predefined operation GetLower of Rex.
  1083.  
  1084.  
  1085.  
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.                             Scanner Specification                           17
  1109.  
  1110.  
  1111. 5.2.  Numeric Literals
  1112.  
  1113. Problems to solve:
  1114.  
  1115. -    conversion
  1116.  
  1117. Solution:
  1118. EXPORT  {
  1119. # include "StringMem.h"
  1120. # include "Positions.h"
  1121. typedef struct {
  1122.    tPosition  Position;
  1123.    tStringRef StringRef;
  1124. } tScanAttribute;
  1125. extern void ErrorAttribute ();
  1126. }
  1127.  
  1128. GLOBAL  {
  1129. # define TokDecimalLiteral ...
  1130. # define TokBasedLiteral ...
  1131. void ErrorAttribute (Token, Attribute) ...
  1132. }
  1133.  
  1134. DEFINE  digit           = {0-9}                 .
  1135.         extended_digit  = digit | {A-F a-f}     .
  1136.         integer         = digit (_? digit) *    .
  1137.         based_integer   = extended_digit (_? extended_digit) *  .
  1138.         exponent        = {Ee} {+\-} ? integer .
  1139.  
  1140. RULE
  1141.  
  1142. integer ("." integer) ? exponent ? :
  1143.                 {Attribute.StringRef = PutString (TokenPtr, TokenLength);
  1144.                  return TokDecimalLiteral;}
  1145.  
  1146. integer "#" based_integer ("." based_integer) ? "#" exponent ? :
  1147.                 {Attribute.StringRef = PutString (TokenPtr, TokenLength);
  1148.                  return TokBasedLiteral;}
  1149.  
  1150.  
  1151.      The conversion of numeric literals to numeric values is not really solved
  1152. in  the  above  solution.  By  storing  the external representation of numeric
  1153. literals in a string memory the  values  are  treated  symbolically  and  true
  1154. conversion is delayed to be done by other compiler phases.
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.                             Scanner Specification                           18
  1174.  
  1175.  
  1176. 5.3.  Character Literals
  1177.  
  1178. Problems to solve:
  1179.  
  1180. -    no problems to solve for character literals
  1181.  
  1182. -    distinction between character literals and apostrophes
  1183.  
  1184. Solution:
  1185. EXPORT  {
  1186. # include "Idents.h"
  1187. # include "Positions.h"
  1188. typedef struct {
  1189.    tPosition Position;
  1190.    char      Char;
  1191.    tIdent    Ident;
  1192. } tScanAttribute;
  1193. extern void ErrorAttribute ();
  1194. }
  1195.  
  1196. GLOBAL  {
  1197. # define TokIdentifier          ...
  1198. # define TokCharacterLiteral    ...
  1199. # define TokApostrophe          ...
  1200. # define TokLParenthesis        ...
  1201. # define TokRParenthesis        ...
  1202. void ErrorAttribute (Token, Attribute) ...
  1203. }
  1204.  
  1205. LOCAL   {char String [256]; int L;}
  1206.  
  1207. DEFINE  character = {\ -~}.
  1208.         letter    = {A-Z a-z}.
  1209.         digit     = {0-9}.
  1210.  
  1211. START   QUOTE
  1212.  
  1213. RULE
  1214.  
  1215. #STD#   ' character '   : {Attribute.Char = TokenPtr [1];
  1216.                            return TokCharacterLiteral;}
  1217. #QUOTE# '               : {yyStart (STD); return TokApostrophe;}
  1218.         "("             : {yyStart (STD); return TokLParenthesis;}
  1219.         ")"             : {yyStart (QUOTE); return TokRParenthesis;}
  1220.         letter (_? (letter | digit)+ )*
  1221.                         : {yyStart (QUOTE); L = GetLower (Word);
  1222.                            Attribute.Ident = MakeIdent (Word, L);
  1223.                            return TokIdentifier;}
  1224.  
  1225.  
  1226.      The tokens Character Literal and Apostrophe can be distinguished  in  Ada
  1227. only  by  consideration of some context. The pathological input is for example
  1228.  
  1229.  
  1230.  
  1231.  
  1232.  
  1233.  
  1234.  
  1235.  
  1236.  
  1237.  
  1238.                             Scanner Specification                           19
  1239.  
  1240.  
  1241. something like
  1242.  
  1243.     t'('a','b','c')
  1244.  
  1245. where t is a type_mark used as qualification for  an  aggregate  of  character
  1246. literals.  It  has  to  be taken care that 'a', 'b', and 'c' are recognized as
  1247. character literals and not '(', ',', and ','. Studying the Ada grammar one can
  1248. see  that  apostrophes  are used following identifiers and closing parentheses
  1249. only. There are never character literals in this places.
  1250.  
  1251.      This leads to the above solution with an additional  start  state  called
  1252. QUOTE.   After  recognition  of  an  identifier  or  a closing parentheses the
  1253. scanner is switched to start state QUOTE.   After  recognition  of  all  other
  1254. tokens  the  scanner  is  switched  back  to start state STD.  Apostrophes are
  1255. recognized only in start state QUOTE and  character  literals  only  in  start
  1256. state STD.  All the other tokens are recognized in both start states.
  1257.  
  1258. 5.4.  String Literals
  1259.  
  1260. Problems to solve:
  1261.  
  1262. -    conversion
  1263.  
  1264. -    doubled delimiters
  1265.  
  1266. -    unclosed strings (at end of lines)
  1267.  
  1268. -    source position
  1269.  
  1270.  
  1271.  
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279.  
  1280.  
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286.  
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.                             Scanner Specification                           20
  1304.  
  1305.  
  1306. Solution:
  1307. EXPORT  {
  1308. # include "StringMem.h"
  1309. # include "Positions.h"
  1310. typedef struct {
  1311.    tPosition  Position;
  1312.    tStringRef StringRef;
  1313. } tScanAttribute;
  1314. extern void ErrorAttribute ();
  1315. }
  1316.  
  1317. GLOBAL  {
  1318. # define TokStringLiteral ...
  1319. void ErrorAttribute (Token, Attribute) ...
  1320. }
  1321.  
  1322. LOCAL   {char String [256]; int L;}
  1323.  
  1324. DEFINE  StrCh   = {\ !#-~}.
  1325.  
  1326. START   string
  1327.  
  1328. RULE
  1329.  
  1330. #STD#    \"     :  {yyStart (string); L = 0;}
  1331. #string# StrCh+ :- {L += GetWord (& String [L]);}
  1332. #string# \"\"   :- {String [L ++] = '\"');}
  1333. #string# \"     :- {yyStart (STD); String [L] = '\0';
  1334.                     Attribute.StringRef = PutString (String, L);
  1335.                     return TokStringLiteral;}
  1336. #string# \n     :- {Error ("unclosed string"); yyEol (0);
  1337.                     yyStart (STD); String [L] = '\0';
  1338.                     Attribute.StringRef = PutString (String, L);
  1339.                     return TokStringLiteral;}
  1340.  
  1341.  
  1342.      We presuppose the existence of a string  memory  module  StringMem.   The
  1343. procedure  PutString stores a string in the string memory and returns a refer-
  1344. ence to it which can be used as attribute of the token TokString.
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.  
  1351.  
  1352.  
  1353.  
  1354.  
  1355.  
  1356.  
  1357.  
  1358.  
  1359.  
  1360.  
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.                             Scanner Specification                           21
  1369.  
  1370.  
  1371. 5.5.  Keywords
  1372.  
  1373. Problems to solve:
  1374.  
  1375. -    normalization of upper-case and lower-case letters
  1376.  
  1377. Solution:
  1378. GLOBAL  {
  1379. # define TokABORT       ...
  1380.    ...
  1381. # define TokXOR         ...
  1382. void ErrorAttribute (Token, Attribute) ...
  1383. }
  1384.  
  1385. DEFINE  A = {Aa}.
  1386.           ...
  1387.         Z = {Zz}.
  1388.  
  1389. RULE
  1390.  
  1391. A B O R T       : {return TokABORT     ;}
  1392.   ...
  1393. X O R           : {return TokXOR       ;}
  1394.  
  1395.  
  1396.      The idea of the solution is to define identifiers A to Z to stand for the
  1397. corresponding  upper-case  as  well as lower-case letters. Then specifying the
  1398. keywords in upper-case and spaced does the job.
  1399.  
  1400.  
  1401.  
  1402.  
  1403.  
  1404.  
  1405.  
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411.  
  1412.  
  1413.  
  1414.  
  1415.  
  1416.  
  1417.  
  1418.  
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.                             Scanner Specification                           22
  1434.  
  1435.  
  1436. Appendix: Complete Scanner Specification for Ada
  1437.  
  1438.  
  1439. GLOBAL  {
  1440.    FROM Strings         IMPORT tString, AssignEmpty, Concatenate, Append, Char;
  1441.    FROM StringMem       IMPORT tStringRef, PutString;
  1442.    FROM Idents          IMPORT tIdent, MakeIdent;
  1443.  
  1444.    PROCEDURE ErrorAttribute (Token: INTEGER; VAR Attribute: tScanAttribute);
  1445.       BEGIN END ErrorAttribute;
  1446.  
  1447. CONST
  1448.    TokIdentifier        =  1    ;
  1449.    TokDecimalLiteral    =  2    ;
  1450.    TokBasedLiteral      =  3    ;
  1451.    TokCharLiteral       =  4    ;
  1452.    TokStringLiteral     =  5    ;
  1453.  
  1454.    TokArrow             =  6    ;       (* '=>'         *)
  1455.    TokDoubleDot         =  7    ;       (* '..'         *)
  1456.    TokDoubleStar        =  8    ;       (* '**'         *)
  1457.    TokBecomes           =  9    ;       (* ':='         *)
  1458.    TokNotEqual          = 10    ;       (* '/='         *)
  1459.    TokGreaterEqual      = 11    ;       (* '>='         *)
  1460.    TokLessEqual         = 12    ;       (* '<='         *)
  1461.    TokLLabelBracket     = 13    ;       (* '<<'         *)
  1462.    TokRLabelBracket     = 14    ;       (* '>>'         *)
  1463.    TokBox               = 15    ;       (* '<>'         *)
  1464.  
  1465.    TokAmpersand         = 16    ;       (* '&'          *)
  1466.    TokApostrophe        = 17    ;       (* '''          *)
  1467.    TokLParenthesis      = 18    ;       (* '('          *)
  1468.    TokRParenthesis      = 19    ;       (* ')'          *)
  1469.    TokStar              = 20    ;       (* '*'          *)
  1470.    TokPlus              = 21    ;       (* '+'          *)
  1471.    TokComma             = 22    ;       (* ','          *)
  1472.    TokMinus             = 23    ;       (* '-'          *)
  1473.    TokDot               = 24    ;       (* '.'          *)
  1474.    TokDivide            = 25    ;       (* '/'          *)
  1475.    TokColon             = 26    ;       (* ':'          *)
  1476.    TokSemicolon         = 27    ;       (* ';'          *)
  1477.    TokLess              = 28    ;       (* '<'          *)
  1478.    TokEqual             = 29    ;       (* '='          *)
  1479.    TokGreater           = 30    ;       (* '>'          *)
  1480.    TokBar               = 31    ;       (* '|'          *)
  1481.  
  1482.    TokABORT             = 32    ;       (* ABORT        *)
  1483.    TokABS               = 33    ;       (* ABS          *)
  1484.    TokACCEPT            = 34    ;       (* ACCEPT       *)
  1485.    TokACCESS            = 35    ;       (* ACCESS       *)
  1486.    TokALL               = 36    ;       (* ALL          *)
  1487.    TokAND               = 37    ;       (* AND          *)
  1488.    TokARRAY             = 38    ;       (* ARRAY        *)
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.                             Scanner Specification                           23
  1500.  
  1501.  
  1502.    TokAT                = 39    ;       (* AT           *)
  1503.    TokBEGIN             = 40    ;       (* BEGIN        *)
  1504.    TokBODY              = 41    ;       (* BODY         *)
  1505.    TokCASE              = 42    ;       (* CASE         *)
  1506.    TokCONSTANT          = 43    ;       (* CONSTANT     *)
  1507.    TokDECLARE           = 44    ;       (* DECLARE      *)
  1508.    TokDELAY             = 45    ;       (* DELAY        *)
  1509.    TokDELTA             = 46    ;       (* DELTA        *)
  1510.    TokDIGITS            = 47    ;       (* DIGITS       *)
  1511.    TokDO                = 48    ;       (* DO           *)
  1512.    TokELSE              = 49    ;       (* ELSE         *)
  1513.    TokELSIF             = 50    ;       (* ELSIF        *)
  1514.    TokEND               = 51    ;       (* END          *)
  1515.    TokENTRY             = 52    ;       (* ENTRY        *)
  1516.    TokEXCEPTION         = 53    ;       (* EXCEPTION    *)
  1517.    TokEXIT              = 54    ;       (* EXIT         *)
  1518.    TokFOR               = 55    ;       (* FOR          *)
  1519.    TokFUNCTION          = 56    ;       (* FUNCTION     *)
  1520.    TokGENERIC           = 57    ;       (* GENERIC      *)
  1521.    TokGOTO              = 58    ;       (* GOTO         *)
  1522.    TokIF                = 59    ;       (* IF           *)
  1523.    TokIN                = 60    ;       (* IN           *)
  1524.    TokIS                = 61    ;       (* IS           *)
  1525.    TokLIMITED           = 62    ;       (* LIMITED      *)
  1526.    TokLOOP              = 63    ;       (* LOOP         *)
  1527.    TokMOD               = 64    ;       (* MOD          *)
  1528.    TokNEW               = 65    ;       (* NEW          *)
  1529.    TokNOT               = 66    ;       (* NOT          *)
  1530.    TokNULL              = 67    ;       (* NULL         *)
  1531.    TokOF                = 68    ;       (* OF           *)
  1532.    TokOR                = 69    ;       (* OR           *)
  1533.    TokOTHERS            = 70    ;       (* OTHERS       *)
  1534.    TokOUT               = 71    ;       (* OUT          *)
  1535.    TokPACKAGE           = 72    ;       (* PACKAGE      *)
  1536.    TokPRAGMA            = 73    ;       (* PRAGMA       *)
  1537.    TokPRIVATE           = 74    ;       (* PRIVATE      *)
  1538.    TokPROCEDURE         = 75    ;       (* PROCEDURE    *)
  1539.    TokRAISE             = 76    ;       (* RAISE        *)
  1540.    TokRANGE             = 77    ;       (* RANGE        *)
  1541.    TokRECORD            = 78    ;       (* RECORD       *)
  1542.    TokREM               = 79    ;       (* REM          *)
  1543.    TokRENAMES           = 80    ;       (* RENAMES      *)
  1544.    TokRETURN            = 81    ;       (* RETURN       *)
  1545.    TokREVERSE           = 82    ;       (* REVERSE      *)
  1546.    TokSELECT            = 83    ;       (* SELECT       *)
  1547.    TokSEPARATE          = 84    ;       (* SEPARATE     *)
  1548.    TokSUBTYPE           = 85    ;       (* SUBTYPE      *)
  1549.    TokTASK              = 86    ;       (* TASK         *)
  1550.    TokTERMINATE         = 87    ;       (* TERMINATE    *)
  1551.    TokTHEN              = 88    ;       (* THEN         *)
  1552.    TokTYPE              = 89    ;       (* TYPE         *)
  1553.    TokUSE               = 90    ;       (* USE          *)
  1554.    TokWHEN              = 91    ;       (* WHEN         *)
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.                             Scanner Specification                           24
  1566.  
  1567.  
  1568.    TokWHILE             = 92    ;       (* WHILE        *)
  1569.    TokWITH              = 93    ;       (* WITH         *)
  1570.    TokXOR               = 94    ;       (* XOR          *)
  1571. }
  1572.  
  1573. LOCAL   {
  1574.    VAR
  1575.       String, S : tString       ;
  1576.       Word      : tString       ;
  1577.       ident     : tIdent        ;
  1578.       string    : tStringRef    ;
  1579.       ch        : CHAR          ;
  1580. }
  1581.  
  1582. DEFINE
  1583.    digit          = {0-9}               .
  1584.    extended_digit = digit | {A-F a-f}   .
  1585.    letter         = {a-z A-Z}           .
  1586.    character      = {\ -~}              .
  1587.    stringch       = {\ !#-~}            .
  1588.    integer        = digit (_? digit) *  .
  1589.    based_integer  = extended_digit (_? extended_digit) *  .
  1590.    illegal        = - {\ \t\n}          .
  1591.  
  1592.    A            = {Aa}  .
  1593.    B            = {Bb}  .
  1594.    C            = {Cc}  .
  1595.    D            = {Dd}  .
  1596.    E            = {Ee}  .
  1597.    F            = {Ff}  .
  1598.    G            = {Gg}  .
  1599.    H            = {Hh}  .
  1600.    I            = {Ii}  .
  1601.    J            = {Jj}  .
  1602.    K            = {Kk}  .
  1603.    L            = {Ll}  .
  1604.    M            = {Mm}  .
  1605.    N            = {Nn}  .
  1606.    O            = {Oo}  .
  1607.    P            = {Pp}  .
  1608.    Q            = {Qq}  .
  1609.    R            = {Rr}  .
  1610.    S            = {Ss}  .
  1611.    T            = {Tt}  .
  1612.    U            = {Uu}  .
  1613.    V            = {Vv}  .
  1614.    W            = {Ww}  .
  1615.    X            = {Xx}  .
  1616.    Y            = {Yy}  .
  1617.    Z            = {Zz}  .
  1618.  
  1619. START   STRING, QUOTE
  1620.  
  1621.  
  1622.  
  1623.  
  1624.  
  1625.  
  1626.  
  1627.  
  1628.  
  1629.  
  1630.                             Scanner Specification                           25
  1631.  
  1632.  
  1633. RULE
  1634.  
  1635. NOT #STRING# integer ("." integer) ? (E {+\-} ? integer) ?
  1636.                         : {yyStart (STD); GetWord (Word);
  1637.                            string := PutString (Word);
  1638.                            RETURN TokDecimalLiteral;}
  1639.  
  1640. NOT #STRING#
  1641.     integer "#" based_integer ("." based_integer) ? "#" (E {+\-} ? integer) ?
  1642.                         : {yyStart (STD); GetWord (Word);
  1643.                            string := PutString (Word);
  1644.                            RETURN TokBasedLiteral;}
  1645.  
  1646.     #STD#  ' character ': {GetWord (String); ch := Char (String, 2);
  1647.                            RETURN TokCharLiteral;}
  1648.  
  1649. NOT #STRING# \"         :  {yyStart (STRING); AssignEmpty (String);}
  1650.     #STRING# stringch + :- {GetWord (S); Concatenate (String, S);}
  1651.     #STRING# \"\"       :- {Append (String, '"');}
  1652.     #STRING# \"         :- {yyStart (STD); string := PutString (String);
  1653.                             RETURN TokStringLiteral;}
  1654.     #STRING# \t         :- {Append (String, 11C); yyTab;}
  1655.     #STRING# \n         :- {(* Error ("unclosed string"); *) yyEol (0);
  1656.                             yyStart (STD); string := PutString (String);
  1657.                             RETURN TokStringLiteral;}
  1658.  
  1659. NOT #STRING# "--" ANY * : {}
  1660.  
  1661. NOT #STRING# "=>"       : {yyStart (STD); RETURN TokArrow               ;}
  1662. NOT #STRING# ".."       : {yyStart (STD); RETURN TokDoubleDot           ;}
  1663. NOT #STRING# "**"       : {yyStart (STD); RETURN TokDoubleStar          ;}
  1664. NOT #STRING# ":="       : {yyStart (STD); RETURN TokBecomes             ;}
  1665. NOT #STRING# "/="       : {yyStart (STD); RETURN TokNotEqual            ;}
  1666. NOT #STRING# ">="       : {yyStart (STD); RETURN TokGreaterEqual        ;}
  1667. NOT #STRING# "<="       : {yyStart (STD); RETURN TokLessEqual           ;}
  1668. NOT #STRING# "<<"       : {yyStart (STD); RETURN TokLLabelBracket       ;}
  1669. NOT #STRING# ">>"       : {yyStart (STD); RETURN TokRLabelBracket       ;}
  1670. NOT #STRING# "<>"       : {yyStart (STD); RETURN TokBox                 ;}
  1671.  
  1672. NOT #STRING# "&"        : {yyStart (STD); RETURN TokAmpersand           ;}
  1673.     #QUOTE#  "'"        : {yyStart (STD); RETURN TokApostrophe          ;}
  1674. NOT #STRING# "("        : {yyStart (STD); RETURN TokLParenthesis        ;}
  1675. NOT #STRING# ")"        : {yyStart (QUOTE); RETURN TokRParenthesis      ;}
  1676. NOT #STRING# "*"        : {yyStart (STD); RETURN TokStar                ;}
  1677. NOT #STRING# "+"        : {yyStart (STD); RETURN TokPlus                ;}
  1678. NOT #STRING# ","        : {yyStart (STD); RETURN TokComma               ;}
  1679. NOT #STRING# "-"        : {yyStart (STD); RETURN TokMinus               ;}
  1680. NOT #STRING# "."        : {yyStart (STD); RETURN TokDot                 ;}
  1681. NOT #STRING# "/"        : {yyStart (STD); RETURN TokDivide              ;}
  1682. NOT #STRING# ":"        : {yyStart (STD); RETURN TokColon               ;}
  1683. NOT #STRING# ";"        : {yyStart (STD); RETURN TokSemicolon           ;}
  1684. NOT #STRING# "<"        : {yyStart (STD); RETURN TokLess                ;}
  1685. NOT #STRING# "="        : {yyStart (STD); RETURN TokEqual               ;}
  1686.  
  1687.  
  1688.  
  1689.  
  1690.  
  1691.  
  1692.  
  1693.  
  1694.  
  1695.  
  1696.                             Scanner Specification                           26
  1697.  
  1698.  
  1699. NOT #STRING# ">"        : {yyStart (STD); RETURN TokGreater             ;}
  1700. NOT #STRING# "|"        : {yyStart (STD); RETURN TokBar                 ;}
  1701.  
  1702. NOT #STRING# A B O R T          : {yyStart (STD); RETURN TokABORT       ;}
  1703. NOT #STRING# A B S              : {yyStart (STD); RETURN TokABS         ;}
  1704. NOT #STRING# A C C E P T        : {yyStart (STD); RETURN TokACCEPT      ;}
  1705. NOT #STRING# A C C E S S        : {yyStart (STD); RETURN TokACCESS      ;}
  1706. NOT #STRING# A L L              : {yyStart (STD); RETURN TokALL         ;}
  1707. NOT #STRING# A N D              : {yyStart (STD); RETURN TokAND         ;}
  1708. NOT #STRING# A R R A Y          : {yyStart (STD); RETURN TokARRAY       ;}
  1709. NOT #STRING# A T                : {yyStart (STD); RETURN TokAT          ;}
  1710. NOT #STRING# B E G I N          : {yyStart (STD); RETURN TokBEGIN       ;}
  1711. NOT #STRING# B O D Y            : {yyStart (STD); RETURN TokBODY        ;}
  1712. NOT #STRING# C A S E            : {yyStart (STD); RETURN TokCASE        ;}
  1713. NOT #STRING# C O N S T A N T    : {yyStart (STD); RETURN TokCONSTANT    ;}
  1714. NOT #STRING# D E C L A R E      : {yyStart (STD); RETURN TokDECLARE     ;}
  1715. NOT #STRING# D E L A Y          : {yyStart (STD); RETURN TokDELAY       ;}
  1716. NOT #STRING# D E L T A          : {yyStart (STD); RETURN TokDELTA       ;}
  1717. NOT #STRING# D I G I T S        : {yyStart (STD); RETURN TokDIGITS      ;}
  1718. NOT #STRING# D O                : {yyStart (STD); RETURN TokDO          ;}
  1719. NOT #STRING# E L S E            : {yyStart (STD); RETURN TokELSE        ;}
  1720. NOT #STRING# E L S I F          : {yyStart (STD); RETURN TokELSIF       ;}
  1721. NOT #STRING# E N D              : {yyStart (STD); RETURN TokEND         ;}
  1722. NOT #STRING# E N T R Y          : {yyStart (STD); RETURN TokENTRY       ;}
  1723. NOT #STRING# E X C E P T I O N  : {yyStart (STD); RETURN TokEXCEPTION   ;}
  1724. NOT #STRING# E X I T            : {yyStart (STD); RETURN TokEXIT        ;}
  1725. NOT #STRING# F O R              : {yyStart (STD); RETURN TokFOR         ;}
  1726. NOT #STRING# F U N C T I O N    : {yyStart (STD); RETURN TokFUNCTION    ;}
  1727. NOT #STRING# G E N E R I C      : {yyStart (STD); RETURN TokGENERIC     ;}
  1728. NOT #STRING# G O T O            : {yyStart (STD); RETURN TokGOTO        ;}
  1729. NOT #STRING# I F                : {yyStart (STD); RETURN TokIF          ;}
  1730. NOT #STRING# I N                : {yyStart (STD); RETURN TokIN          ;}
  1731. NOT #STRING# I S                : {yyStart (STD); RETURN TokIS          ;}
  1732. NOT #STRING# L I M I T E D      : {yyStart (STD); RETURN TokLIMITED     ;}
  1733. NOT #STRING# L O O P            : {yyStart (STD); RETURN TokLOOP        ;}
  1734. NOT #STRING# M O D              : {yyStart (STD); RETURN TokMOD         ;}
  1735. NOT #STRING# N E W              : {yyStart (STD); RETURN TokNEW         ;}
  1736. NOT #STRING# N O T              : {yyStart (STD); RETURN TokNOT         ;}
  1737. NOT #STRING# N U L L            : {yyStart (STD); RETURN TokNULL        ;}
  1738. NOT #STRING# O F                : {yyStart (STD); RETURN TokOF          ;}
  1739. NOT #STRING# O R                : {yyStart (STD); RETURN TokOR          ;}
  1740. NOT #STRING# O T H E R S        : {yyStart (STD); RETURN TokOTHERS      ;}
  1741. NOT #STRING# O U T              : {yyStart (STD); RETURN TokOUT         ;}
  1742. NOT #STRING# P A C K A G E      : {yyStart (STD); RETURN TokPACKAGE     ;}
  1743. NOT #STRING# P R A G M A        : {yyStart (STD); RETURN TokPRAGMA      ;}
  1744. NOT #STRING# P R I V A T E      : {yyStart (STD); RETURN TokPRIVATE     ;}
  1745. NOT #STRING# P R O C E D U R E  : {yyStart (STD); RETURN TokPROCEDURE   ;}
  1746. NOT #STRING# R A I S E          : {yyStart (STD); RETURN TokRAISE       ;}
  1747. NOT #STRING# R A N G E          : {yyStart (STD); RETURN TokRANGE       ;}
  1748. NOT #STRING# R E C O R D        : {yyStart (STD); RETURN TokRECORD      ;}
  1749. NOT #STRING# R E M              : {yyStart (STD); RETURN TokREM         ;}
  1750. NOT #STRING# R E N A M E S      : {yyStart (STD); RETURN TokRENAMES     ;}
  1751. NOT #STRING# R E T U R N        : {yyStart (STD); RETURN TokRETURN      ;}
  1752.  
  1753.  
  1754.  
  1755.  
  1756.  
  1757.  
  1758.  
  1759.  
  1760.  
  1761.  
  1762.                             Scanner Specification                           27
  1763.  
  1764.  
  1765. NOT #STRING# R E V E R S E      : {yyStart (STD); RETURN TokREVERSE     ;}
  1766. NOT #STRING# S E L E C T        : {yyStart (STD); RETURN TokSELECT      ;}
  1767. NOT #STRING# S E P A R A T E    : {yyStart (STD); RETURN TokSEPARATE    ;}
  1768. NOT #STRING# S U B T Y P E      : {yyStart (STD); RETURN TokSUBTYPE     ;}
  1769. NOT #STRING# T A S K            : {yyStart (STD); RETURN TokTASK        ;}
  1770. NOT #STRING# T E R M I N A T E  : {yyStart (STD); RETURN TokTERMINATE   ;}
  1771. NOT #STRING# T H E N            : {yyStart (STD); RETURN TokTHEN        ;}
  1772. NOT #STRING# T Y P E            : {yyStart (STD); RETURN TokTYPE        ;}
  1773. NOT #STRING# U S E              : {yyStart (STD); RETURN TokUSE         ;}
  1774. NOT #STRING# W H E N            : {yyStart (STD); RETURN TokWHEN        ;}
  1775. NOT #STRING# W H I L E          : {yyStart (STD); RETURN TokWHILE       ;}
  1776. NOT #STRING# W I T H            : {yyStart (STD); RETURN TokWITH        ;}
  1777. NOT #STRING# X O R              : {yyStart (STD); RETURN TokXOR         ;}
  1778.  
  1779. NOT #STRING# letter (_? (letter | digit)+ )*
  1780.                                 : {yyStart (QUOTE); GetLower (Word);
  1781.                                    ident := MakeIdent (Word);
  1782.                                    RETURN TokIdentifier;}
  1783.  
  1784. NOT #STRING# illegal            : {IO.WriteS (IO.StdOutput, "illegal character: ");
  1785.                                    yyEcho; IO.WriteNl (IO.StdOutput);}
  1786.  
  1787. References
  1788.  
  1789. [Gro87]
  1790.      J. Grosch, Rex - A Scanner Generator, Compiler Generation Report  No.  5,
  1791.      GMD Forschungsstelle an der Universitat Karlsruhe, Dec. 1987.
  1792.  
  1793.  
  1794.  
  1795.  
  1796.  
  1797.  
  1798.  
  1799.  
  1800.  
  1801.  
  1802.  
  1803.  
  1804.  
  1805.  
  1806.  
  1807.  
  1808.  
  1809.  
  1810.  
  1811.  
  1812.  
  1813.  
  1814.  
  1815.  
  1816.  
  1817.  
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825.  
  1826.  
  1827.                             Scanner Specification                            1
  1828.  
  1829.  
  1830. Contents
  1831.  
  1832. 1.      Introduction ....................................................    2
  1833. 2.      Pascal ..........................................................    2
  1834. 2.1.    Comments ........................................................    2
  1835. 2.2.    Identifiers .....................................................    3
  1836. 2.3.    Character Constants .............................................    5
  1837. 2.4.    Strings .........................................................    6
  1838. 2.5.    Keywords ........................................................    8
  1839. 3.      Modula ..........................................................    9
  1840. 3.1.    Comments ........................................................    9
  1841. 3.2.    Strings .........................................................   10
  1842. 4.      C ...............................................................   12
  1843. 4.1.    Comments ........................................................   12
  1844. 4.2.    Character Constants .............................................   13
  1845. 4.3.    Strings .........................................................   14
  1846. 5.      Ada .............................................................   16
  1847. 5.1.    Identifiers .....................................................   16
  1848. 5.2.    Numeric Literals ................................................   17
  1849. 5.3.    Character Literals ..............................................   18
  1850. 5.4.    String Literals .................................................   19
  1851. 5.5.    Keywords ........................................................   21
  1852.         Appendix: Complete Scanner Specification for Ada ................   22
  1853.         References ......................................................   27
  1854.  
  1855.  
  1856.  
  1857.  
  1858.  
  1859.  
  1860.  
  1861.  
  1862.  
  1863.  
  1864.  
  1865.  
  1866.  
  1867.  
  1868.  
  1869.  
  1870.  
  1871.  
  1872.  
  1873.  
  1874.  
  1875.  
  1876.  
  1877.  
  1878.  
  1879.  
  1880.  
  1881.  
  1882.  
  1883.  
  1884.  
  1885.  
  1886.  
  1887.  
  1888.